//
//  SipManager.m
//  SipPhone
//
//  Created by 宋晓建 on 2019/6/21.
//  Copyright © 2019 SJ. All rights reserved.
//

#import "SipManager.h"

#import <AVFoundation/AVFoundation.h>
#import <pjsua.h>
#import <SVProgressHUD.h>

#import "ConnectView.h"

#define SERVER @"47.91.146.58:6066"
#define USERNAME @"80085800005"
#define PASSWORD @"cH@1694323"
//
// #define SERVER @"77.72.174.132"
// #define USERNAME @"jiayou112233"
// #define PASSWORD @"Qwe123321"

pjsua_acc_id global_acc_id;
pjsua_call_id global_call_id;

void init_sua(void); // 初始化
void login(void); // 登录
void call(NSString *number); // 拨号
void hangup(void); // 挂断

void on_reg_state(pjsua_acc_id acc_id); // 登录状态回调
void on_call_state(pjsua_call_id call_id, pjsip_event *e); // 电话状态回调
void on_call_media_state(pjsua_call_id call_id); // 媒体状态回调（通话建立后，要播放RTP流）

@interface SipManager ()

@property (weak, nonatomic) NSTimer *connectTimer;
@property (assign, nonatomic) NSUInteger connectTime;
//@property (nonatomic,strong)dygUserModel *userModel;
@end

@implementation SipManager

+ (instancetype)sharedManager {
    static SipManager *manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [self new];
        // SVProgressHUD
        [SVProgressHUD setDefaultStyle:SVProgressHUDStyleDark];
        [SVProgressHUD setDefaultMaskType:SVProgressHUDMaskTypeClear];
    });
    return manager;
}

- (void)login {
    init_sua();
}

- (void)initError:(NSString *)status {
    [SVProgressHUD showErrorWithStatus:status];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [SVProgressHUD showWithStatus:@"正在初始化"];
        init_sua();
    });
}

- (void)loginError:(NSString *)status {
    [SVProgressHUD showErrorWithStatus:status];
    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        if (status == AFNetworkReachabilityStatusReachableViaWiFi || status == AFNetworkReachabilityStatusReachableViaWWAN) {
            [[AFNetworkReachabilityManager sharedManager] stopMonitoring];
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                login();
            });
        } else if (status == AFNetworkReachabilityStatusNotReachable) {
            [SVProgressHUD showErrorWithStatus:@"无法连接网络\n请检查网络设置"];
            [SVProgressHUD dismissWithDelay:1.5];
        
        } else {
            [SVProgressHUD showErrorWithStatus:@"Network Status Unknown"];
            [SVProgressHUD dismissWithDelay:1.5];
        }
    }];
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
}

// 拨号
- (void)call:(NSString *)number {
    
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    if (status == AVAuthorizationStatusAuthorized) {
        [self allowConnect:number];
    
    } else if (status == AVAuthorizationStatusNotDetermined) {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self allowConnect:number];
                });
            }
        }];
        
    } else if (status == AVAuthorizationStatusDenied) {
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
        UIAlertAction *open = [UIAlertAction actionWithTitle:@"去开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            if ([[UIApplication sharedApplication] canOpenURL:url]) {
                [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
            }
        }];
        
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"已禁止使用麦克风" message:@"是否前往系统设置开启麦克风使用权限？" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:cancel];
        [alert addAction:open];
        [[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:alert animated:YES completion:nil];
        
    } else if (status == AVAuthorizationStatusRestricted) {
        
    }
}

// 挂断
- (void)hangup {
    hangup();
}
// 通话计时
- (void)startRecordTime {
    __weak typeof(self)weakSelf = self;
    _connectTime = 0;
    _connectTimer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:true block:^(NSTimer * _Nonnull timer) {
        weakSelf.connectTime += 1;
        
        [ConnectView sharedView].time = [NSString stringWithFormat:@"%02ld:%02ld", weakSelf.connectTime / 60, weakSelf.connectTime % 60];
        // 每55秒扣费一次
        if (weakSelf.connectTime % 55 == 0) {
            [weakSelf payBalance];
        }
    }];
}

// 停止计时
- (void)stopRecordTime {
    if (_connectTimer) {
        [_connectTimer invalidate];
    }
}

// 拨号之前 判断拨打中国号码次数 判断余额
- (void)allowConnect:(NSString *)number {
//    KeychainItemWrapper *callChina = [[KeychainItemWrapper alloc] initWithIdentifier:@"callChina" accessGroup:nil];
//    NSString *count = [callChina objectForKey:(__bridge id)kSecValueData];
    
//    if ([count integerValue] >= 5) {
//        UIAlertAction *done = [UIAlertAction actionWithTitle:Localized(@"OK") style:UIAlertActionStyleDefault handler:nil];
//
//        UIAlertController *alert = [UIAlertController alertControllerWithTitle:Localized(@"You can dial the China number five times") message:Localized(@"Your number of calls has reached the limit") preferredStyle:UIAlertControllerStyleAlert];
//        [alert addAction:done];
//        [[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:alert animated:YES completion:nil];
//        return;
//    }
    
//    if ([[number substringToIndex:3] isEqualToString:@"+86"]) {
//        [callChina setObject:[NSString stringWithFormat:@"%ld", [count integerValue] + 1] forKey:(__bridge id)kSecValueData];
//    }
    
//    KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"balance" accessGroup:nil];
//    NSString *balance = [wrapper objectForKey:(__bridge id)kSecValueData];

//    if ([balance isEqualToString:@"试用1次"]) {
//        call(number);
//
//    } else if ([balance integerValue] > 0) {
//        call(number);
//
//    } else {
//        UIAlertAction *done = [UIAlertAction actionWithTitle:Localized(@"OK") style:UIAlertActionStyleDefault handler:nil];
//
//        UIAlertController *alert = [UIAlertController alertControllerWithTitle:Localized(@"The balance is not enough") message:Localized(@"Please recharge") preferredStyle:UIAlertControllerStyleAlert];
//        [alert addAction:done];
//        [[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:alert animated:YES completion:nil];
//    }
    
    call(number);
}

// 试用结束
- (void)probationDone {
//    KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"balance" accessGroup:nil];
//    NSString *balance = [wrapper objectForKey:(__bridge id)kSecValueData];
//
//    if ([balance isEqualToString:@"试用1次"]) {
//        [wrapper setObject:@"" forKey:(__bridge id)kSecValueData];
//    }
}

// 扣费
- (void)payBalance {
//      int min=  [[DygCommon backUserDefaut:@"guoji"] intValue];
//       [DygCommon writeKeyName:@"guoji" ForMessage:[NSString stringWithFormat:@"%i",min - 1]];
    
//    NSString *act = [[NSUserDefaults standardUserDefaults]  objectForKey:@"account"];
//    NetRequestManager *manager = [NetRequestManager shareManager];
//    NSMutableDictionary *dic = [DygCommon publicDataDictionary];
//    [dic setObject:act forKey:@"mobile"];
//    [dic setObject:@"1" forKey:@"min"];
//    NSString * result = [DygCommon generateNormalizedString:dic];
//    NSString * sign = [DygCommon md5:[NSString stringWithFormat:@"%@%@",result,Skey]];
//    [dic setObject:sign forKey:@"sign"];
//    [manager POST:[NSString stringWithFormat:@"%@reduce_min",RootUrl] parameters:dic cachepolicy:1 success:^(NSDictionary *dataDic) {
//
//    } failure:^(NSError *erro) {
//
//    }];
//    KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"balance" accessGroup:nil];
//    NSString *balance = [wrapper objectForKey:(__bridge id)kSecValueData];
//
//    if ([balance isEqualToString:@"试用1次"]) {
//
//        if (self.connectTime >= 55 * 3) { // 已试用3分钟
//            [self hangup];
//
//            UIAlertAction *done = [UIAlertAction actionWithTitle:Localized(@"OK") style:UIAlertActionStyleDefault handler:nil];
//
//            UIAlertController *alert = [UIAlertController alertControllerWithTitle:Localized(@"Trial closed") message:Localized(@"Please recharge") preferredStyle:UIAlertControllerStyleAlert];
//            [alert addAction:done];
//            [[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:alert animated:YES completion:nil];
//        }
//
//    } else if ([balance integerValue] > 0) {
//        [wrapper setObject:[NSString stringWithFormat:@"%ld分钟", [balance integerValue] - 1] forKey:(__bridge id)kSecValueData];
//
//    } else {
//        [self hangup];
//
//        UIAlertAction *done = [UIAlertAction actionWithTitle:Localized(@"OK") style:UIAlertActionStyleDefault handler:nil];
//
//        UIAlertController *alert = [UIAlertController alertControllerWithTitle:Localized(@"The balance is not enough") message:Localized(@"Please recharge") preferredStyle:UIAlertControllerStyleAlert];
//        [alert addAction:done];
//        [[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:alert animated:YES completion:nil];
//    }
}

@end

void init_sua() {
    
    pj_status_t status;
    
    // 创建SUA
    status = pjsua_create();
    
    if (status != PJ_SUCCESS) {
        pjsua_destroy();
        
        [[SipManager sharedManager] initError:@"sua create error"];
        return;
    }
    
    {
        // SUA 相关配置
        pjsua_config cfg;
        pjsua_media_config media_cfg;
        pjsua_logging_config log_cfg;
        
        pjsua_config_default(&cfg);
        
        // 回调函数配置
        cfg.cb.on_reg_state = &on_reg_state;
        cfg.cb.on_call_state = &on_call_state;
        cfg.cb.on_call_media_state = &on_call_media_state;
        
        // 媒体相关配置
        pjsua_media_config_default(&media_cfg);
        media_cfg.clock_rate = 16000;
        media_cfg.snd_clock_rate = 16000;
        media_cfg.ec_tail_len = 0;
        
        // 日志相关配置
        pjsua_logging_config_default(&log_cfg);
//#ifdef DEBUG
//        log_cfg.msg_logging = PJ_TRUE;
//        log_cfg.console_level = 4;
//        log_cfg.level = 5;
//#else
        log_cfg.msg_logging = PJ_FALSE;
        log_cfg.console_level = 0;
        log_cfg.level = 0;
//#endif
        
        // 初始化PJSUA
        status = pjsua_init(&cfg, &log_cfg, &media_cfg);
        if (status != PJ_SUCCESS) {
            pjsua_destroy();
            
            [[SipManager sharedManager] initError:@"sua init error"];
            return;
        }
    }
    
    // udp transport
    {
        pjsua_transport_config cfg;
        pjsua_transport_config_default(&cfg);
        
        // 传输类型配置
        status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
        if (status != PJ_SUCCESS) {
            pjsua_destroy();
            
            [[SipManager sharedManager] initError:@"sua transport create error"];
            return;
        }
    }
    
    // 启动PJSUA
    status = pjsua_start();
    if (status != PJ_SUCCESS) {
        pjsua_destroy();
        
        [[SipManager sharedManager] initError:@"sua start error"];
        return;
    }
    
    login();
}

void login() {
    [SVProgressHUD showWithStatus:@"正在连接服务"];
    pjsua_acc_id acc_id;
    pjsua_acc_config cfg;
    pjsua_acc_config_default(&cfg);
    cfg.id = pj_str((char *)[NSString stringWithFormat:@"sip:%@@%@",USERNAME,SERVER].UTF8String); // 用户名@IP
    cfg.reg_uri = pj_str((char *)[NSString stringWithFormat:@"sip:%@", SERVER].UTF8String); // IP
    cfg.reg_retry_interval = 0;
    cfg.cred_count = 1;
    cfg.cred_info[0].realm = pj_str("*");
    cfg.cred_info[0].username = pj_str((char *)USERNAME.UTF8String); // 用户名
    cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
    cfg.cred_info[0].data = pj_str((char *)PASSWORD.UTF8String); // 密码
    
    pj_status_t status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
    
    if (status == PJ_SUCCESS) {
        [SipManager sharedManager].logined = true;
    } else {
        [[SipManager sharedManager] loginError:@"sua acc add error"];
    }
    [SVProgressHUD dismiss];
}

void call(NSString *number) {
//    dygUserModel *usermodel = [dygUserModel sharedInstance];
    NSString *targetUri = [NSString stringWithFormat:@"sip:%@@%@", number, SERVER];
    
    pj_str_t dest_uri = pj_str((char *)targetUri.UTF8String);
    
    pj_status_t status = pjsua_call_make_call(global_acc_id, &dest_uri, 0, NULL, NULL, &global_call_id);
    
    if (status == PJ_SUCCESS) {
        [ConnectView sharedView].number = number;
        [ConnectView sharedView].time = @"";
        [[ConnectView sharedView] show];

    } else {
        char errMessage[PJ_ERR_MSG_SIZE];
        pj_strerror(status, errMessage, sizeof(errMessage));
        
        [SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"%d %s", status, errMessage]];
        [SVProgressHUD dismissWithDelay:1];
    }
}

void hangup() {
    pj_status_t status = pjsua_call_hangup(global_call_id, 0, NULL, NULL);
    
    if (status != PJ_SUCCESS) {
        pj_str_t statusText = *pjsip_get_status_text(status);
        
        [SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"%d %s", status, statusText.ptr]];
        [SVProgressHUD dismissWithDelay:1];
    }
}

void on_reg_state(pjsua_acc_id acc_id) {
    pjsua_acc_info info;
    pj_status_t status = pjsua_acc_get_info(acc_id, &info);
    dispatch_async(dispatch_get_main_queue(), ^{
        if (status != PJ_SUCCESS) {
            pjsua_acc_del(acc_id);
            [[SipManager sharedManager] loginError:@"sua acc get info error"];
            return;
        }
        global_acc_id = acc_id;
        if (info.status == PJSIP_SC_OK) {
            
            [SVProgressHUD showSuccessWithStatus:@"连接服务成功"];
            [SVProgressHUD dismissWithDelay:1];
            
        } else {
            pjsua_acc_del(acc_id);
            
            [[SipManager sharedManager] loginError:[NSString stringWithFormat:@"%d %s", info.status, info.status_text.ptr]];
        }
    });
}

void on_call_state(pjsua_call_id call_id, pjsip_event *e) {
    
    pjsua_call_info ci;
    pjsua_call_get_info(call_id, &ci);
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        if(call_id != global_call_id) {
            [SVProgressHUD showErrorWithStatus:@"拨号失败"];
            [SVProgressHUD dismissWithDelay:1.5];
            
            return;
        }
        
        if (ci.state == PJSIP_INV_STATE_CALLING) { // 正在拨号
            [ConnectView sharedView].time = @"正在呼叫...";
            
            [[SipManager sharedManager] payBalance]; // 无论是否接通，电话播出弹到通话页面，扣费一次

        } else if (ci.state == PJSIP_INV_STATE_EARLY) { // 等待接听
            [ConnectView sharedView].time = @"等待接听...";
            
        } else if (ci.state == PJSIP_INV_STATE_CONNECTING) { // 对方接听
            [ConnectView sharedView].time = @"00:00";

            [[SipManager sharedManager] startRecordTime];

//            [ConnectView sharedView].time = @"正在接通...";
//
//        } else if (ci.state == PJSIP_INV_STATE_CONFIRMED) { // 开始通话
//            [ConnectView sharedView].time = @"00:00";
            
        } else if (ci.state == PJSIP_INV_STATE_DISCONNECTED) { // 通话结束
            // 保存通话记录
//            NSString *time = [NSString stringWithFormat:@"%02ld:%02ld", [SipManager sharedManager].connectTime / 60, [SipManager sharedManager].connectTime % 60];
//            NSDictionary *record = @{
//                                     @"number": [ConnectView sharedView].number,
//                                     @"detail": @"",
//                                     @"time": time,
//                                     };
//
//            NSMutableArray *recordArray = [[[NSUserDefaults standardUserDefaults] objectForKey:@"CallRecords"] ?: @[] mutableCopy];
//            [recordArray insertObject:record atIndex:0];
//            [[NSUserDefaults standardUserDefaults] setObject:recordArray forKey:@"CallRecords"];
//            if ([SipManager sharedManager].addCallRecord) {
//                [SipManager sharedManager].addCallRecord(record);
//            }
            
            [[ConnectView sharedView] hide];
            
            [[SipManager sharedManager] stopRecordTime];
            
            [[SipManager sharedManager] probationDone];
        }
    });
}

void on_call_media_state(pjsua_call_id call_id) {
    
    pjsua_call_info ci;
    pjsua_call_get_info(call_id, &ci);
    
    // When media is active, connect call to sound device.
    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
        pjsua_conf_connect(ci.conf_slot, 0);
        pjsua_conf_connect(0, ci.conf_slot);
    }
}
